/*
 ********************************************************************************** 
  Classe do controle principal
 **********************************************************************************
 */
public class controle {
  private byte regDst;
  private byte origAlu;
  private byte memParaReg;
  private byte escreveReg;
  private byte leMem;           /********* Atributos para armazenar cada um dos sinais de controle *****/
  private byte escreveMem;
  private byte branch;
  private byte aluOp0;
  private byte aluOp1;
  private byte opAlu;
  private byte inverteZero;
  private byte jump;
  private byte salvaPC;
  private String controleAlu;

  public String getControleAlu() {
    return controleAlu;
  }
  

  //Construtor inicializa todos os sinais de controle com 0
  public controle() {
    regDst = 0;
    origAlu = 0;
    memParaReg = 0;
    escreveReg = 0;
    leMem = 0;
    escreveMem = 0;
    branch = 0;
    aluOp0 = 0;
    aluOp1 = 0;
    opAlu = 00;
    controleAlu = "0000";
    inverteZero = 0;
    salvaPC = 0 ;
    jump = 0;
  }
  
  
  
  //Seta os sinais para istruções R
  public void setSinais(instrucaoR inst){
    regDst = 1;
    origAlu = 0;
    memParaReg = 0;
    escreveReg = 1;
    leMem = 0;
    escreveMem = 0;
    branch = 0;
    aluOp0 = 0;
    aluOp1 = 1;
    opAlu = 10;
    inverteZero = 0;
    jump = 0;
    salvaPC = 0 ;
    
    int funct = inst.getFunct();
    switch(funct){
      case instrucaoR.FUNCT_ADD:{
        controleAlu = "0010";
        break;
      }
      case instrucaoR.FUNCT_AND:{
        controleAlu = "0000";
        break;
      }
      case instrucaoR.FUNCT_DIV:{
        controleAlu = "1110"; 
        break;
      }
      case instrucaoR.FUNCT_JR:{
        controleAlu = "0010";
        jump = 1;
        break;
      }
      case instrucaoR.FUNCT_MULT:{
        controleAlu = "1111";  
        break;
      }
      case instrucaoR.FUNCT_OR:{
        controleAlu = "0001";
        break;
      }
      case instrucaoR.FUNCT_SLL:{
        origAlu = 1;
        controleAlu = "0011";  //Não sei
        break;
      }
      case instrucaoR.FUNCT_SLT:{
        controleAlu = "0111";
        break;
      }
      case instrucaoR.FUNCT_SUB:{
        controleAlu = "0110";
        break;
      }  
    }
  }
  
  //Seta os sinais para istruções J
  public void setSinais(instrucaoJ inst){
    jump = 1;
    salvaPC = 0;
    if (inst.getOpCode() == instrucaoJ.OPCODE_JAL){
      salvaPC = 1;
    }
  }
  
  //Seta os sinais para istruções I
  public void setSinais(instrucaoI inst){
    int opCode = inst.getOpCode();
    switch (opCode){
      case instrucaoI.OPCODE_BEQ:{
        regDst = 0;
        memParaReg = 0;
        origAlu = 0;
        escreveReg = 0;
        leMem = 0;
        escreveMem = 0;
        branch = 1;
        aluOp0 = 1;
        aluOp1 = 0;
        opAlu = 01;
        controleAlu = "0110";
        inverteZero = 0;
        jump = 0;
        salvaPC = 0 ;
        break;
      }
      case instrucaoI.OPCODE_BNE: {
        memParaReg = 0;
        regDst = 0;
        origAlu = 0;
        escreveReg = 0;
        leMem = 0;
        escreveMem = 0;
        branch = 1;
        aluOp0 = 1;
        aluOp1 = 0;
        opAlu = 01;
        controleAlu = "0110";
        inverteZero = 1;
        jump = 0;
        salvaPC = 0 ;
        break;
      }
      case instrucaoI.OPCODE_ADDI:{
        escreveMem = 0;
        memParaReg = 0;
        controleAlu = "0010";
        jump = 0;
        salvaPC = 0 ;
        break;
      }
      case instrucaoI.OPCODE_LW:{
        regDst = 0;
        origAlu = 1;
        memParaReg = 1;
        escreveReg = 1;
        leMem = 1;
        escreveMem = 0;
        branch = 0;
        aluOp0 = 0;
        aluOp1 = 0;
        opAlu = 00;
        controleAlu = "0010";
        inverteZero = 0;
        jump = 0;
        salvaPC = 0 ;
        break;
      }
      case instrucaoI.OPCODE_SW:{
        memParaReg = 0;
        regDst = 0;
        origAlu = 1;
        escreveReg = 0;
        leMem = 0;
        escreveMem = 1;
        branch = 0;
        aluOp0 = 0;
        aluOp1 = 0;
        opAlu = 00;
        controleAlu = "0010";
        inverteZero = 0;
        jump = 0;
        salvaPC = 0 ;
        break;
      }
    }  
  }

  public int getAluOp1() {
    return aluOp1;
  }

  public int getAluOp0() {
    return aluOp0;
  }

  public int getBranch() {
    return branch;
  }

  public int getEscreveMem() {
    return escreveMem;
  }

  public int getEscreveReg() {
    return escreveReg;
  }

  public int getLeMem() {
    return leMem;
  }

  public int getMemParaReg() {
    return memParaReg;
  }

  public int getOrigAlu() {
    return origAlu;
  }

  public int getRegDst() {
    return regDst;
  }

  public byte getInverteZero() {
    return inverteZero;
  }

  public byte getJump() {
    return jump;
  }

  public byte getSalvaPC() {
    return salvaPC;
  }
  
  
  
  
  
  
}
